﻿using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text;

namespace Chbl.Scheduling
{
    public class Scheduler
    {
        public List<ITeam> Teams { get; set; }
        [Required]
        public DateTime StartDate { get; set; }
        [Range(1, 30)]
        public int TourIntervalInDays { get; set; }

        public Schedule Generate()
        {
            if (!TeamsNumberNotEvenOrZero)
            {
                throw new InvalidOperationException("Teams number must be even");
            }
            var schedule = new Schedule();
            var tourDate = StartDate;

            int numTeams = Teams.Count();
            int numDays = (numTeams - 1);
            int halfSize = numTeams / 2;

            var internalTeams = new List<ITeam>();

            internalTeams.AddRange(Teams); // Copy all the elements.
            internalTeams.RemoveAt(0); // To exclude the first team.

            int teamsSize = internalTeams.Count;

            for (int day = 0; day < numDays; day++)
            {
                int gameOrder = 0;
                int teamIdx = day % teamsSize;
                schedule.GamesList.Add(new Game
                                           {
                                               Date = tourDate,
                                               GameOrder = ++gameOrder,
                                               HomeTeam = internalTeams[teamIdx],
                                               RoadTeam = Teams[0],
                                               TourNumber = day + 1
                                           });

                for (int idx = 1; idx < halfSize; idx++)
                {
                    int firstTeam = (day + idx) % teamsSize;
                    int secondTeam = (day + teamsSize - idx) % teamsSize;
                    schedule.GamesList.Add(new Game
                                               {
                                                   Date = tourDate,
                                                   GameOrder = ++gameOrder,
                                                   HomeTeam = internalTeams[firstTeam],
                                                   RoadTeam = internalTeams[secondTeam],
                                                   TourNumber = day + 1
                                               });
                }

                schedule.GamesDaysList.Add(tourDate);
                tourDate = tourDate.AddDays(TourIntervalInDays);
            }

            return schedule;
        }

        public bool TeamsNumberNotEvenOrZero
        {
            get { return (Teams == null || Teams.Count%2 == 0) ? true : false; }
        }
    }
}
